package com.atguigu.lease.common.utils;

import com.atguigu.lease.common.exception.LeaseException;
import com.atguigu.lease.common.result.ResultCodeEnum;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.ExpiredJwtException;
import io.jsonwebtoken.JwtException;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.security.Keys;

import javax.crypto.SecretKey;
import java.util.Date;

/**
 * Package: com.atguigu.lease.common.utils
 *
 * @Description:
 * @Author xiongkunYang
 * @Create 2025/5/4 11:21
 */

public class JwtUtil {
    // 定义Token的过期时间，这里设置为60分钟
    private static final long TOKEN_EXPIRATION = 60 * 60 * 1000L;

    // 定义Token的签名密钥，使用HMAC-SHA算法，密钥需要保持保密
    private static final SecretKey TOKEN_SIGN_KEY = Keys.hmacShaKeyFor("xmxQXSLUwC2SpdvVEFVnaLeH7CR7dCDd".getBytes());

    /**
     * 创建一个用户Token
     *
     * @param userId   用户ID，用于标识用户
     * @param username 用户名，用于在Token中标识用户
     * @return 返回生成的Token字符串
     */
    public static String createToken(Long userId, String username) {
        // 使用JJWT库构建Token
        return Jwts.builder()
                // 设置Token的主题
                .subject("USER_INFO")
                // 设置Token的过期时间
                .expiration(new Date(System.currentTimeMillis() + TOKEN_EXPIRATION * 24 * 30 * 365))
                // 在Token中添加用户ID声明
                .claim("userId", userId)
                // 在Token中添加用户名声明
                .claim("username", username)
                // 使用HS256算法签名Token
                .signWith(TOKEN_SIGN_KEY, Jwts.SIG.HS256)
                // 对Token进行压缩以减小体积
                .compressWith(Jwts.ZIP.GZIP)
                // 最终生成并返回Token字符串
                .compact();
    }

    /**
     * 解析JWT令牌，提取并返回其中的声明信息
     *
     * @param token 待解析的JWT令牌字符串
     * @return 包含令牌中声明信息的Claims对象
     * @throws LeaseException 当令牌过期或无效时抛出的异常
     */
    public static Claims parseToken(String token) {
        try {
            // 使用预定义的密钥构建JWT解析器，并解析令牌
            return Jwts.parser()
                    .verifyWith(TOKEN_SIGN_KEY)
                    .build()
                    .parseSignedClaims(token)
                    .getPayload();
        } catch (ExpiredJwtException e) {
            // 捕获过期异常，抛出异常
            throw new LeaseException(ResultCodeEnum.TOKEN_EXPIRED);
        } catch (JwtException e) {
            // 捕获其他JWT异常，抛出异常
            throw new LeaseException(ResultCodeEnum.TOKEN_INVALID);
        }
    }
}